package com.example.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.concurrent.*;

@Service
@Slf4j
public class ForkJoinPoolApiService {

    private final ForkJoinPool forkJoinPool = new ForkJoinPool(4);  // 自定义并行度为 4 的 ForkJoinPool

    // 使用 invoke() 方法执行任务并等待结果
    public int executeTaskWithInvoke() {
        ForkJoinTask<Integer> task = new SumTask(new int[]{1, 2, 3, 4, 5}, 0, 5);
        log.info("使用 invoke() 启动任务并等待结果...");
        return forkJoinPool.invoke(task);  // 阻塞直到任务完成
    }

    // 使用 submit() 方法提交任务并返回 Future
    public Future<Integer> executeTaskWithSubmit() {
        ForkJoinTask<Integer> task = new SumTask(new int[]{1, 2, 3, 4, 5}, 0, 5);
        log.info("使用 submit() 提交任务...");
        return forkJoinPool.submit(task);  // 返回 Future 对象
    }

    // 使用 execute() 方法执行任务但不等待结果
    public void executeTaskWithoutWaiting() {
        ForkJoinTask<Integer> task = new SumTask(new int[]{1, 2, 3, 4, 5}, 0, 5);
        log.info("使用 execute() 执行任务但不等待结果...");
        forkJoinPool.execute(task);  // 不阻塞当前线程
    }

    // 关闭 ForkJoinPool
    public void shutdownForkJoinPool() {
        log.info("正在关闭 ForkJoinPool...");
        forkJoinPool.shutdown();  // 关闭线程池，不再接受新任务
        try {
            //true：如果在给定的时间内，线程池的所有任务都完成了。
            //false：如果在超时时间内，仍有未完成的任务。
            if (!forkJoinPool.awaitTermination(5, TimeUnit.SECONDS)) {
                log.warn("线程池未在5秒内终止，强制关闭...");
                forkJoinPool.shutdownNow();  // 强制关闭
            }
        } catch (InterruptedException e) {
            log.error("线程池关闭时被中断", e);
            forkJoinPool.shutdownNow();
        }
    }

    // SumTask 用于演示 ForkJoin 任务
    private static class SumTask extends RecursiveTask<Integer> {
        private static final int THRESHOLD = 2;
        private final int[] array;
        private final int start;
        private final int end;

        public SumTask(int[] array, int start, int end) {
            this.array = array;
            this.start = start;
            this.end = end;
        }

        @Override
        protected Integer compute() {
            if (end - start <= THRESHOLD) {
                int sum = 0;
                for (int i = start; i < end; i++) {
                    sum += array[i];
                }
                log.info("计算部分结果: [{} - {}] 的和为: {}", start, end, sum);
                return sum;
            } else {
                int mid = (start + end) / 2;
                SumTask leftTask = new SumTask(array, start, mid);
                SumTask rightTask = new SumTask(array, mid, end);
                invokeAll(leftTask, rightTask);  // 分解任务
                int leftResult = leftTask.join();  // 获取左侧结果
                int rightResult = rightTask.join();  // 获取右侧结果
                log.info("合并结果: {} + {} = {}", leftResult, rightResult, leftResult + rightResult);
                return leftResult + rightResult;
            }
        }
    }
}
